package com.oa.order.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;  

import javax.annotation.Resource;

import org.activiti.engine.IdentityService;
import org.activiti.engine.ManagementService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.impl.persistence.entity.IdentityLinkEntity;
import org.activiti.engine.impl.persistence.entity.TaskEntity;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.NativeTaskQuery;
import org.activiti.engine.task.Task;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


import com.oa.order.dao.OrderDao;
import com.oa.order.dto.OrderDTO;
import com.oa.order.entity.Order;
import com.oa.organization.dao.OrganizationDao;
import com.oa.organization.entity.Organization;
import com.oa.system.dao.AccountDao;
import com.oa.system.dao.UserInfoDao;

@Service
@Transactional
public class OrderServiceImpl implements OrderService {
	/**
	 * 系统服务
	 */
	@Resource
	private OrderDao orderDao;
	@Resource
	private UserInfoDao userInfoDao;
	@Resource
	private OrganizationDao organzationDao;
	@Resource
	private AccountDao accountDao;
	/**
	 * 流程服务
	 */
	@Resource
	private IdentityService identityService;
	@Resource
	private RuntimeService runtimeService;
	@Resource
	private ManagementService managementService;
	@Resource
	private TaskService taskService;
	@Resource
	private RepositoryService repositoryService;
	
	//系统业务
	@Override
	public void save(Order order) {
		orderDao.save(order);
	}
	@Override
	public void delete(Long orderId) {
		Order order = orderDao.findOne(orderId);
		if (order != null) {
			orderDao.delete(order);
		}
	}
	@Override
	public Order findOne(Long orderId) {
		return orderDao.findOne(orderId);
	}
	@Override
	public Page<Order> findByOne(String userName, Pageable pageable) {
		return orderDao.findByOne(userName, pageable);
	}

	@Override
	public Page<Order> findAll(Specification<Order> spec, Pageable pageable) {
		return orderDao.findAll(spec,pageable);
	}

	//流程业务
	@Override
	public ProcessInstance startWorkflow(Long orderId, Map<String, Object> variables) 
	{
		//1.声明流程实例
		ProcessInstance processInstance = null;
		//2.获取创建好的订餐实例
		Order order = orderDao.findOne(orderId);
		if(order!=null){
			try {

				//3.授权
				identityService.setAuthenticatedUserId(order.getUserName());
				//4.把entityid转换为业务主键(用于工作流程实例关联业务)
				String businessKey = order.getOrderId().toString();	
				//5.启动流程实例:processDefinitionKey, businessKey, variables
				processInstance = runtimeService.startProcessInstanceByKey("order", businessKey, variables);
				//6.业务实体与流程实例关联
				order.setProcessInstanceId(processInstance.getId());
				order.setApplyTime(new Date());
				//7.更新到数据库
				//orderDao.save(order);
			} catch (Exception e) {
				e.printStackTrace();
			}finally {
				//8.取消授权
				identityService.setAuthenticatedUserId(null);
			}
		}
		return processInstance;
	}

	@Override
	public Page<OrderDTO> findTodoTasks(Long userId, Pageable pageable) 
	{
		List<OrderDTO> results = new ArrayList<>();
        // 根据当前人的ID查询
		// 根据当前用户Id查询待完成流程任务
		// 用于原生查询的sql语句
		String sql = "select * from " + managementService.getTableName(TaskEntity.class) + " T left join  "
				+ managementService.getTableName(IdentityLinkEntity.class)
				+ " I on I.TASK_ID_ = T.ID_ where I.GROUP_ID_ = #{group} and T.ASSIGNEE_ is null or T.ASSIGNEE_ = #{assignee};";
		// 使用原生查询查找当前用户待完成的流程任务Id
		NativeTaskQuery taskQuery = taskService.createNativeTaskQuery().sql(sql)
				.parameter("group", userInfoDao.findOne(userId).getRole().getRole())
				.parameter("assignee",  accountDao.findOne(userId).getUsername());
		List<Task> tasks = taskQuery.list();
        // 根据流程的业务ID查询实体并关联
        for (Task task : tasks) {
            String processInstanceId = task.getProcessInstanceId();
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).active().singleResult();
            String businessKey = processInstance.getBusinessKey();
            if (businessKey == null) {
                continue;
            }
            Order order = orderDao.findOne(new Long(businessKey));
            if(order!=null){
            	OrderDTO orderDTO = new OrderDTO();
            	BeanUtils.copyProperties(order, orderDTO);
            	orderDTO.setTaskId(task.getId());
            	orderDTO.setTaskName(task.getName());
            	orderDTO.setTaskCreateTime(task.getCreateTime());
            	orderDTO.setAssignee(task.getAssignee());
            	orderDTO.setTaskDefinitionKey(task.getTaskDefinitionKey());
            	orderDTO.setSuspended(processInstance.isSuspended());
            	ProcessDefinition processDefinition = getProcessDefinition(processInstance.getProcessDefinitionId());
            	orderDTO.setProcessDefinitionId(processDefinition.getId());
            	orderDTO.setVersion(processDefinition.getVersion());
            	
            	results.add(orderDTO);
            }
        }
        //results List进行排序
        //封装为Page返回
		return new PageImpl<OrderDTO> (results, pageable, results.size());
	}

	@Override
	public Page<OrderDTO> findRunningProcessInstaces(Page<Order> page, int[] pageParams) {	
		return null;
	}

	@Override
	public Page<OrderDTO> findFinishedProcessInstaces(Page<Order> page, int[] pageParams) {
		return null;
	}
	 /**
     * 查询流程定义对象
     *
     * @param processDefinitionId 流程定义ID
     * @return
     */
    protected ProcessDefinition getProcessDefinition(String processDefinitionId) {
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();
        return processDefinition;
    }

    /**
     * 签收流程任务
     *
     * @param taskId 任务ID
     * @param userId 签收人用户ID
     * @return
     */
	public void claim(String taskId, String userName) {
		taskService.claim(taskId, userName);
		
	}

	 /**
     * 完成流程任务
     *
     * @param taskId 任务ID
     * @param variables 流程变量
     * @return
     */
	public void complete(String taskId, Map<String, Object> variables) {
		taskService.complete(taskId, variables);
	}

}
